package com.chat.utils;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import com.alibaba.druid.util.Base64;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
public class ZXingCode {
	private static final int QRCOLOR = 0xFF000000; 
	private static final int BGWHITE = 0xFFFFFFFF;
	public static String getLogoQRCode(String qrUrl, HttpServletRequest request,
			String productName, String imgFile, String filePath) {
		String content = qrUrl;
		try {
			ZXingCode zp = new ZXingCode();
			BufferedImage bim = zp.getQR_CODEBufferedImage(content,
					BarcodeFormat.QR_CODE, 400, 400, zp.getDecodeHintType());
			return zp.addLogo_QRCode(bim, new File(imgFile), new LogoConfig(),
					productName, filePath);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	public String addLogo_QRCode(BufferedImage bim, File logoPic,
			LogoConfig logoConfig, String productName, String filePath) {
		try {
			BufferedImage image = bim;
			Graphics2D g = image.createGraphics();
			BufferedImage logo = ImageIO.read(logoPic);
			int widthLogo = logo.getWidth(null) > image.getWidth() * 3 / 10
					? (image.getWidth() * 3 / 10)
					: logo.getWidth(null),
					heightLogo = logo.getHeight(null) > image.getHeight() * 3
							/ 10
									? (image.getHeight() * 3 / 10)
									: logo.getWidth(null);

			int x = (image.getWidth() - widthLogo) / 2;
			int y = (image.getHeight() - heightLogo) / 2;
			g.drawImage(logo, x, y, widthLogo, heightLogo, null);
			g.dispose();
			if (productName != null && !productName.equals("")) {
				BufferedImage outImage = new BufferedImage(400, 445,
						BufferedImage.TYPE_4BYTE_ABGR);
				Graphics2D outg = outImage.createGraphics();
				outg.drawImage(image, 0, 0, image.getWidth(), image.getHeight(),
						null);
				outg.setColor(Color.BLACK);
				outg.setFont(new Font("宋体", Font.BOLD, 30)); 
				int strWidth = outg.getFontMetrics().stringWidth(productName);
				if (strWidth > 399) {
					String productName1 = productName.substring(0,
							productName.length() / 2);
					String productName2 = productName.substring(
							productName.length() / 2, productName.length());
					int strWidth1 = outg.getFontMetrics()
							.stringWidth(productName1);
					int strWidth2 = outg.getFontMetrics()
							.stringWidth(productName2);
					outg.drawString(
							productName1, 200
									- strWidth1 / 2,
							image.getHeight()
									+ (outImage.getHeight() - image.getHeight())
											/ 2
									+ 12);
					BufferedImage outImage2 = new BufferedImage(400, 485,
							BufferedImage.TYPE_4BYTE_ABGR);
					Graphics2D outg2 = outImage2.createGraphics();
					outg2.drawImage(outImage, 0, 0, outImage.getWidth(),
							outImage.getHeight(), null);
					outg2.setColor(Color.BLACK);
					outg2.setFont(new Font("宋体", Font.BOLD, 28)); 
					outg2.drawString(
							productName2, 200
									- strWidth2 / 2,
							outImage.getHeight() + (outImage2.getHeight()
									- outImage.getHeight()) / 2 + 5);
					outg2.dispose();
					outImage2.flush();
					outImage = outImage2;
				} else {
					outg.drawString(
							productName, 200
									- strWidth / 2,
							image.getHeight()
									+ (outImage.getHeight() - image.getHeight())
											/ 2
									+ 12); 
				}
				outg.dispose();
				outImage.flush();
				image = outImage;
			}
			logo.flush();
			image.flush();
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			baos.flush();
			ImageIO.write(image, "png", baos);
			ImageIO.write(image, "png", new File(filePath)); // TODO
			String imageBase64QRCode = Base64
					.byteArrayToBase64(baos.toByteArray());
			baos.close();
			return imageBase64QRCode;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	public BufferedImage fileToBufferedImage(BitMatrix bm) {
		BufferedImage image = null;
		try {
			int w = bm.getWidth(), h = bm.getHeight();
			image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
			for (int x = 0; x < w; x++) {
				for (int y = 0; y < h; y++) {
					image.setRGB(x, y, bm.get(x, y) ? 0xFF000000 : 0xFFCCDDEE);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return image;
	}
	public BufferedImage getQR_CODEBufferedImage(String content,
			BarcodeFormat barcodeFormat, int width, int height,
			Map<EncodeHintType, ?> hints) {
		MultiFormatWriter multiFormatWriter = null;
		BitMatrix bm = null;
		BufferedImage image = null;
		try {
			multiFormatWriter = new MultiFormatWriter();
			bm = multiFormatWriter.encode(content, barcodeFormat, width, height,
					hints);
			int w = bm.getWidth();
			int h = bm.getHeight();
			image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
			for (int x = 0; x < w; x++) {
				for (int y = 0; y < h; y++) {
					image.setRGB(x, y, bm.get(x, y) ? QRCOLOR : BGWHITE);
				}
			}
		} catch (WriterException e) {
			e.printStackTrace();
		}
		return image;
	}
	public Map<EncodeHintType, Object> getDecodeHintType() {
		Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
		hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
		hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
		hints.put(EncodeHintType.MARGIN, 0);
		hints.put(EncodeHintType.MAX_SIZE, 350);
		hints.put(EncodeHintType.MIN_SIZE, 100);
		return hints;
	}
}
class LogoConfig {
	public static final Color DEFAULT_BORDERCOLOR = Color.WHITE;
	public static final int DEFAULT_BORDER = 2;
	public static final int DEFAULT_LOGOPART = 4;
	private final int border = DEFAULT_BORDER;
	private final Color borderColor;
	private final int logoPart;
	public LogoConfig() {
		this(DEFAULT_BORDERCOLOR, DEFAULT_LOGOPART);
	}
	public LogoConfig(Color borderColor, int logoPart) {
		this.borderColor = borderColor;
		this.logoPart = logoPart;
	}
	public Color getBorderColor() {
		return borderColor;
	}
	public int getBorder() {
		return border;
	}
	public int getLogoPart() {
		return logoPart;
	}
}
